package middleware

//管理入参和出参的类
import (
	"bytes"
	"errors"
	"io"
	"net/http"

	"hermestrans/basis/utils"
	bvalidator "hermestrans/basis/validator"

	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"github.com/sirupsen/logrus"
)

// 不封装成类方便外部调用
type EncMsgHandler struct {
	Context *gin.Context
}

func GetMsg(code int) string {
	msg, ok := utils.MsgFlags[code]
	if ok {
		return msg
	}
	return utils.MsgFlags[http.StatusNotFound]
}

func ErrResponse(c *gin.Context, code int, msg interface{}) {
	//TODO 业务打点到prometheus！
	logrus.Error(msg)
	MakeResponse(c, http.StatusInternalServerError, code, msg)
}

func SuccessResponse(c *gin.Context, code int, msg interface{}) {
	logrus.Info(msg)
	MakeResponse(c, http.StatusOK, code, msg)
}

func MakeResponse(c *gin.Context, httpStatus, code int, msg interface{}) {
	resp := gin.H{
		"code":   code,
		"msg":    GetMsg(code),
		"detail": msg,
	}

	c.JSON(httpStatus, resp)
}

func FormBind(c *gin.Context, obj interface{}) error {
	trans, err := bvalidator.InitTrans("zh")

	if err != nil {
		return err
	}

	if err := c.ShouldBind(obj); err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok && errs != nil {
			return errs
		}

		for _, v := range errs.Translate(trans) {
			return errors.New(v)
		}

	}
	return nil
}

func Html(c *gin.Context, code int, name string, data gin.H) {
	if data == nil {
		data = gin.H{}
	}

	uid, _ := c.Get("uid")
	username, _ := c.Get("username")
	groupname, _ := c.Get("groupname")
	data["username"] = username
	data["uid"] = uid
	data["groupname"] = groupname

	c.HTML(code, name, data)
}

func GetControlHandler(c *gin.Context) *EncMsgHandler {
	return c.MustGet(utils.PrefixGinController).(*EncMsgHandler)
}

func ParseParams() gin.HandlerFunc {
	return func(c *gin.Context) {
		h := &EncMsgHandler{Context: c}
		//上下文填充
		c.Set(utils.PrefixGinController, h)

		buf, err := io.ReadAll(c.Request.Body)
		c.Request.Body = io.NopCloser(bytes.NewBuffer(buf))
		if err != nil {
			//错误信息
			ErrResponse(c, utils.JsonRequired, err.Error())
			return
		}
		//设置上下文参数
		c.Set(utils.PrefixParams, string(buf))

		if !c.IsAborted() {
			c.Next()
		}
	}
}
